package net.myBill;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

import android.app.ExpandableListActivity;
import android.app.ProgressDialog;
import android.net.ParseException;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class myBill extends ExpandableListActivity {
    private static String LOGTAG = "myBill - debug";
    private final int VISIBLE = 0;
    private final int GONE = 8;

    private TextView ownerText, ownerValue, updateTimeText, updateTimeValue,
	    totalText, totalValue;
    private Button goButton;
    private RadioButton sdRadio, urlRadio;
    String inputString = null;

    private ProgressDialog progressDialog;

    ArrayList<HashMap<String, String>> groupList = new ArrayList<HashMap<String, String>>();
    ArrayList<ArrayList<HashMap<String, String>>> childList = new ArrayList<ArrayList<HashMap<String, String>>>();
    HashMap<String, HashMap<String, String>> noChildList = new HashMap<String, HashMap<String, String>>();

    private String deafultFile = "bill2.html";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);

	goButton = (Button) this.findViewById(R.id.goButton);
	sdRadio = (RadioButton) this.findViewById(R.id.sdRadio);
	urlRadio = (RadioButton) this.findViewById(R.id.urlRadio);
	ownerText = (TextView) this.findViewById(R.id.ownerText);
	ownerValue = (TextView) this.findViewById(R.id.ownerValue);
	updateTimeText = (TextView) this.findViewById(R.id.updateTimeText);
	updateTimeValue = (TextView) this.findViewById(R.id.updateTimeValue);
	totalText = (TextView) this.findViewById(R.id.totalText);
	totalValue = (TextView) this.findViewById(R.id.totalValue);

	goButton.setOnClickListener(new View.OnClickListener() {
	    public void onClick(View v) {
		progressDialog = ProgressDialog.show(myBill.this, "",
			"Getting Data...");
		new Thread() {
		    public void run() {
			groupList.clear();
			childList.clear();
			noChildList.clear();
			messageHandler.sendMessage(Message.obtain(
				messageHandler, 1));
			getDataString();
			messageHandler.sendMessage(Message.obtain(
				messageHandler, 2));
			matchData(inputString);
			messageHandler.sendMessage(Message.obtain(
				messageHandler, 3));
		    }
		}.start();
	    }
	});
	DefaultHttpClient dhc = getClient();
	HttpResponse hr = doPost(
		"http://www.whatsup.co.il/user.php?op=loginscreen&module=NS-User",
		"blabla", "blabla", dhc);
	String s = getResponseBody(hr);
	Log.d(LOGTAG, s);
    }

    public static HttpResponse doPost(String mUrl, String username,
	    String password, DefaultHttpClient httpClient) {
	HttpResponse response = null;
	if (username != null && password != null) {
	    httpClient.getCredentialsProvider().setCredentials(
		    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
		    new UsernamePasswordCredentials(username, password));
	}
	HttpPost postMethod = new HttpPost(mUrl);
	// if (hm == null)
	// return null;
	try {
	    // List<NameValuePair> nameValuePairs = new
	    // ArrayList<NameValuePair>(2);
	    // Iterator<String> it = hm.keySet().iterator();
	    // String k, v;
	    // while (it.hasNext()) {
	    // k = it.next();
	    // v = hm.get(k);
	    // nameValuePairs.add(new BasicNameValuePair(k, v));
	    // }
	    // postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
	    response = httpClient.execute(postMethod);
	    Log.d(LOGTAG, "STATUS CODE: "
		    + String.valueOf(response.getStatusLine().getStatusCode()));
	} catch (Exception e) {
	    Log.e("Exception", e.getMessage());
	} finally {
	}
	return response;
    }

    public DefaultHttpClient getClient() {
	DefaultHttpClient ret = null;

	// sets up parameters
	HttpParams params = new BasicHttpParams();
	HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
	HttpProtocolParams.setContentCharset(params, "utf-8");
	params.setBooleanParameter("http.protocol.expect-continue", false);

	// registers schemes for both http and https
	SchemeRegistry registry = new SchemeRegistry();
	registry.register(new Scheme("http", PlainSocketFactory
		.getSocketFactory(), 80));
	final SSLSocketFactory sslSocketFactory = SSLSocketFactory
		.getSocketFactory();
	sslSocketFactory
		.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
	registry.register(new Scheme("https", sslSocketFactory, 443));

	ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(
		params, registry);
	ret = new DefaultHttpClient(manager, params);
	return ret;
    }

    public static String getResponseBody(HttpResponse response) {
	String response_text = null;
	HttpEntity entity = null;
	try {
	    entity = response.getEntity();
	    response_text = _getResponseBody(entity);
	} catch (ParseException e) {
	    e.printStackTrace();
	} catch (IOException e) {
	    if (entity != null) {
		try {
		    entity.consumeContent();
		} catch (IOException e1) {
		}
	    }
	}
	return response_text;
    }

    public static String _getResponseBody(final HttpEntity entity)
	    throws IOException, ParseException {
	if (entity == null) {
	    throw new IllegalArgumentException("HTTP entity may not be null");
	}
	InputStream instream = entity.getContent();
	if (instream == null) {
	    return "";
	}
	if (entity.getContentLength() > Integer.MAX_VALUE) {
	    throw new IllegalArgumentException(
		    "HTTP entity too large to be buffered in memory");
	}
	String charset = getContentCharSet(entity);
	if (charset == null) {
	    charset = HTTP.DEFAULT_CONTENT_CHARSET;
	}

	Reader reader = new InputStreamReader(instream, charset);
	StringBuilder buffer = new StringBuilder();
	try {
	    char[] tmp = new char[1024];
	    int l;
	    while ((l = reader.read(tmp)) != -1) {
		buffer.append(tmp, 0, l);
	    }
	} finally {
	    reader.close();
	}
	return buffer.toString();
    }

    public static String getContentCharSet(final HttpEntity entity)
	    throws ParseException {
	if (entity == null) {
	    throw new IllegalArgumentException("HTTP entity may not be null");
	}
	String charset = null;
	if (entity.getContentType() != null) {
	    HeaderElement values[] = entity.getContentType().getElements();
	    if (values.length > 0) {
		NameValuePair param = values[0].getParameterByName("charset");
		if (param != null) {
		    charset = param.getValue();
		}
	    }
	}
	return charset;
    }

    private Handler messageHandler = new Handler() {
	public void handleMessage(Message msg) {
	    switch (msg.what) {
	    case 1:
		progressDialog.setMessage("Getting Data...");
		break;
	    case 2:
		progressDialog.setMessage("Analyzing Data...");
		break;
	    case 3:
		progressDialog.dismiss();
		updateGui();
	    }
	}
    };

    private void createListView() {
	SimpleExpandableListAdapter mAdapter = new SimpleExpandableListAdapter(
		this, groupList, R.layout.group_row, new String[] { "category",
			"value" }, new int[] { R.id.groupname, R.id.value },
		childList, R.layout.child_row, new String[] { "description",
			"value" }, new int[] { R.id.childname, R.id.value });
	setListAdapter(mAdapter);
    }

    private void updateGui() {
	ownerText.setText(noChildList.get("owner").get("category"));
	ownerText.setVisibility(VISIBLE);
	ownerValue.setText(noChildList.get("owner").get("value"));
	ownerValue.setVisibility(VISIBLE);
	updateTimeText.setText(noChildList.get("updateTime").get("category"));
	updateTimeText.setVisibility(VISIBLE);
	updateTimeValue.setText(noChildList.get("updateTime").get("value"));
	updateTimeValue.setVisibility(VISIBLE);
	totalText.setText(noChildList.get("total").get("category"));
	totalText.setVisibility(VISIBLE);
	totalValue.setText(noChildList.get("total").get("value"));
	totalValue.setVisibility(VISIBLE);
	createListView();
    }

    private void getDataString() {
	if (sdRadio.isChecked()) {
	    inputString = getStringFromFile(deafultFile);
	}
	if (urlRadio.isChecked()) {
	    inputString = null;
	}
	if (inputString == null) {
	    return;
	}
    }

    private void matchData(String inputString) {
	String startElement, endElement = null;

	{
	    // find owner
	    {
		startElement = "option value=\"1";
		endElement = "option";
		HashMap<String, String> groupOwner = new HashMap<String, String>();
		groupOwner.put("category", "Onwer :");
		groupOwner.put("value", removeHtmlChars(getHtmlData(
			inputString, startElement, endElement, 1, 1)));
		noChildList.put("owner", groupOwner);
	    }
	}
	{
	    // find update time
	    {
		startElement = "BlackBoldFont CurrentStatement_LastCalldate";
		endElement = "img";
		HashMap<String, String> groupUpdateTime = new HashMap<String, String>();
		groupUpdateTime.put("category", "Update Time :");
		groupUpdateTime.put("value", removeHtmlChars(getHtmlData(
			inputString, startElement, endElement, 1, 1)));
		noChildList.put("updateTime", groupUpdateTime);
	    }
	}
	{
	    // find calls
	    {
		startElement = "PLC_BB PLC_BL OrangeBoldFont";
		endElement = "td";
		HashMap<String, String> groupCalls = new HashMap<String, String>();
		groupCalls.put("category", "Total Calls :");
		groupCalls.put("value",
			leaveOnlyDigits(removeHtmlChars(getHtmlData(
				inputString, startElement, endElement, 1, 1))));
		groupList.add(groupCalls);
	    }
	    {
		ArrayList<HashMap<String, String>> secListCalls = new ArrayList<HashMap<String, String>>();
		{
		    // Total calls time
		    startElement = "PLC_Dark  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashCalls1 = new HashMap<String, String>();
		    secListHashCalls1.put("description", "Total Calls Time :");
		    secListHashCalls1.put("value", removeHtmlChars(getHtmlData(
			    inputString, startElement, endElement, 2, 2)));
		    secListCalls.add(secListHashCalls1);
		}
		{
		    // Total calls time to charge
		    startElement = "PLC_Dark  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashCalls2 = new HashMap<String, String>();
		    secListHashCalls2.put("description", "Total Charge Time :");
		    secListHashCalls2.put("value", removeHtmlChars(getHtmlData(
			    inputString, startElement, endElement, 3, 2)));
		    secListCalls.add(secListHashCalls2);
		}
		childList.add(secListCalls);
	    }
	}
	{
	    // find data
	    {
		startElement = "PLC_BB PLC_BL OrangeBoldFont";
		endElement = "td";
		HashMap<String, String> groupData = new HashMap<String, String>();
		groupData.put("category", "Total Data :");
		groupData.put("value",
			leaveOnlyDigits(removeHtmlChars(getHtmlData(
				inputString, startElement, endElement, 2, 1))));
		groupList.add(groupData);
	    }
	    {
		ArrayList<HashMap<String, String>> secListData = new ArrayList<HashMap<String, String>>();
		{
		    // Total used data
		    startElement = "PLC_Dark  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashData1 = new HashMap<String, String>();
		    secListHashData1.put("description", "Total Data Used :");
		    secListHashData1.put("value", removeHtmlChars(getHtmlData(
			    inputString, startElement, endElement, 7, 2)));
		    secListData.add(secListHashData1);
		}
		{
		    // Total data to charge
		    startElement = "PLC_Dark  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashData2 = new HashMap<String, String>();
		    secListHashData2.put("description", "Total Charge Data :");
		    secListHashData2.put("value", removeHtmlChars(getHtmlData(
			    inputString, startElement, endElement, 8, 2)));
		    secListData.add(secListHashData2);
		}
		childList.add(secListData);
	    }
	}
	{
	    {
		// find sms
		startElement = "PLC_BB PLC_BL OrangeBoldFont";
		endElement = "td";
		HashMap<String, String> groupSms = new HashMap<String, String>();
		groupSms.put("category", "Total Sms :");
		groupSms.put("value",
			leaveOnlyDigits(removeHtmlChars(getHtmlData(
				inputString, startElement, endElement, 3, 1))));
		groupList.add(groupSms);
	    }
	    {
		ArrayList<HashMap<String, String>> secListSms = new ArrayList<HashMap<String, String>>();
		{
		    // Total used sms
		    startElement = "PLC_Dark  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashSms1 = new HashMap<String, String>();
		    secListHashSms1.put("description", "Total Sms Used :");
		    secListHashSms1.put("value", removeHtmlChars(getHtmlData(
			    inputString, startElement, endElement, 16, 2)));
		    secListSms.add(secListHashSms1);
		}
		{
		    // Total sms to charge
		    startElement = "PLC_Dark  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashSms2 = new HashMap<String, String>();
		    secListHashSms2.put("description", "Total Charge Sms :");
		    secListHashSms2.put("value", removeHtmlChars(getHtmlData(
			    inputString, startElement, endElement, 17, 2)));
		    secListSms.add(secListHashSms2);

		}
		childList.add(secListSms);
	    }
	}
	{
	    {
		// find fixed
		startElement = "PLC_BB PLC_BL OrangeBoldFont";
		endElement = "td";
		HashMap<String, String> groupFixed = new HashMap<String, String>();
		groupFixed.put("category", "Total Fixed :");
		groupFixed.put("value",
			leaveOnlyDigits(removeHtmlChars(getHtmlData(
				inputString, startElement, endElement, 4, 1))));
		groupList.add(groupFixed);
	    }
	    {
		ArrayList<HashMap<String, String>> secListFixed = new ArrayList<HashMap<String, String>>();
		{
		    // fixed item 1
		    startElement = "PLC_Dark  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashFixed1 = new HashMap<String, String>();
		    secListHashFixed1.put("description",
			    removeHtmlChars(getHtmlData(inputString,
				    startElement, endElement, 19, 2)));
		    startElement = "PLC_Dark  PLC_BL  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    secListHashFixed1
			    .put(
				    "value",
				    leaveOnlyDigits(removeHtmlChars(getHtmlData(
					    inputString, startElement,
					    endElement, 5, 2))));
		    secListFixed.add(secListHashFixed1);
		}
		{
		    // fixed item 2
		    startElement = "PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashFixed2 = new HashMap<String, String>();
		    secListHashFixed2.put("description",
			    removeHtmlChars(getHtmlData(inputString,
				    startElement, endElement, 41, 2)));
		    startElement = "PLC_BL  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    secListHashFixed2
			    .put(
				    "value",
				    leaveOnlyDigits(removeHtmlChars(getHtmlData(
					    inputString, startElement,
					    endElement, 9, 2))));
		    secListFixed.add(secListHashFixed2);
		}
		{
		    // fixed item 3
		    startElement = "PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    HashMap<String, String> secListHashFixed3 = new HashMap<String, String>();
		    secListHashFixed3.put("description",
			    removeHtmlChars(getHtmlData(inputString,
				    startElement, endElement, 44, 2)));
		    startElement = "PLC_BL  PLC_BB PLC_BR BlackFont CurrentStatement_CustomerTbl1";
		    endElement = "td";
		    secListHashFixed3.put("value",
			    leaveOnlyDigits(removeHtmlChars(getHtmlData(
				    inputString, startElement, endElement, 10,
				    2))));
		    secListFixed.add(secListHashFixed3);
		}
		childList.add(secListFixed);
	    }
	}
	{
	    // find total
	    {
		startElement = "PLC_BT PLC_BB PLC_BR PLC_BL BlackBoldFont CurrentStatement_TotalTbl PLC_White";
		endElement = "td";
		HashMap<String, String> groupTotal = new HashMap<String, String>();
		groupTotal.put("category", "Total Cost :");
		groupTotal.put("value",
			leaveOnlyDigits(removeHtmlChars(getHtmlData(
				inputString, startElement, endElement, 1, 1))));
		noChildList.put("total", groupTotal);
	    }
	}
    }

    private String leaveOnlyDigits(String inputString) {
	if (inputString == null) {
	    return null;
	}
	return inputString.replaceAll("[^\\d\\.]", "");
    }

    private String removeHtmlChars(String inputString) {
	if (inputString == null) {
	    return null;
	}
	Pattern pattern = Pattern.compile("&.*?;");
	Matcher matcher = pattern.matcher(inputString);
	return matcher.replaceAll("");
    }

    private String getHtmlData(String inputString, String startElement,
	    String endElement, Integer lineNumber, Integer tagNumber) {
	if (inputString == null) {
	    return null;
	}
	String lookForPattern = startElement + "(.*?)" + endElement;
	// Log.d(LOGTAG, "look for pattern - " + lookForPattern);
	Pattern pattern = Pattern.compile(lookForPattern);
	Matcher matcher = pattern.matcher(inputString);
	Integer j = 1;
	String found = null;
	while (j <= lineNumber) {
	    if (matcher.find()) {
		found = matcher.group(1);
		// Log.d(LOGTAG, "found - " + matcher.group(1));
	    }
	    j++;
	}
	if ((found == null) || (tagNumber == 0)) {
	    return found;
	}
	// if (tagNumber == 0) {
	// return found;
	// return matcher.group(1);
	// }
	return getHtmlTagValue(found, tagNumber);
	// return getHtmlTagValue(matcher.group(1), tagNumber);
    }

    private String getHtmlTagValue(String inputString, Integer tagNumber) {
	if (inputString == null) {
	    return null;
	}
	String lookForInsidePattern = ">(.*?)<";
	Pattern patternInside = Pattern.compile(lookForInsidePattern);
	Matcher matcherInside = patternInside.matcher(inputString);
	Integer j = 1;
	String found = null;
	while (j <= tagNumber) {
	    if (matcherInside.find()) {
		found = matcherInside.group(1);
		// Log.d(LOGTAG, "found inside - " + matcherInside.group(1));
	    }
	    j++;
	}
	return found;
	// return matcherInside.group(1);
    }

    private String getStringFromFile(String inputFile) {
	String inputString = "";
	try {
	    File f = new File(Environment.getExternalStorageDirectory() + "/"
		    + inputFile);
	    if (!f.exists()) {
		Thread popup = new Thread() {
		    public void run() {
			try {
			    Toast.makeText(myBill.this, "Missing File",
				    Toast.LENGTH_LONG).show();
			} catch (Exception e) {
			}
		    }
		};
		this.runOnUiThread(popup);
		return null;
	    }
	    FileInputStream fileIS = new FileInputStream(f);
	    BufferedReader buf = new BufferedReader(new InputStreamReader(
		    fileIS));
	    String readString = new String();

	    while ((readString = buf.readLine()) != null) {
		inputString += readString;
	    }
	} catch (Exception e) {
	    e.printStackTrace();
	    Log.d(LOGTAG, "error: " + e.toString());
	}
	return inputString;
    }

    private String getStringFromUrl(String link) {
	link = link.replace(" ", "%20");
	Scanner reader;
	StringBuilder builder;
	try {
	    reader = new Scanner(new URL(link).openStream());
	    builder = new StringBuilder();
	    while (reader.hasNext()) {
		builder.append(reader.nextLine() + "\n");
	    }
	    return builder.toString();
	} catch (MalformedURLException e) {
	    Log.d(LOGTAG, "error: " + e.toString());
	} catch (IOException e) {
	    Log.d(LOGTAG, "error: " + e.toString());
	}
	return "error";
    }
}